package com.bolt.core.view.config;

import com.bolt.common.io.resource.ClassPathResource;
import com.bolt.core.view.components.PageView;
import com.bolt.core.view.templates.FreemarkerTemplateEngine;
import org.apache.commons.digester.Digester;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.context.support.ServletContextResourcePatternResolver;
import org.xml.sax.SAXException;

import javax.servlet.ServletContext;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


public class PageRepository implements InitializingBean, DisposableBean, ResourceLoaderAware, ServletContextAware {

    private static Logger logger = LoggerFactory.getLogger(PageRepository.class);

    private final FreemarkerTemplateEngine engine;

    private final UIProperties uiProperties;


    private final String pattern = "/*.xml";


    final Map <String, PageView> pages = new HashMap <>();


    private ResourceLoader resourceLoader;

    private ServletContextResourcePatternResolver resourcePatternResolver;

    private Digester configDigester;

    private ServletContext servletContext;



    public PageRepository(FreemarkerTemplateEngine engine, UIProperties uiProperties) {
        this.engine = engine;
        this.uiProperties = uiProperties;
    }

    @Override
    public void setResourceLoader(ResourceLoader rl) {
        this.resourceLoader = rl;
        resourcePatternResolver = new ServletContextResourcePatternResolver(resourceLoader);
    }

    @Override
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    @Override
    public void destroy() throws Exception {
        pages.clear();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        init();
    }

    public void init() {
        initConfigDigester();

    }


    /**
     * 读取目录所有表单配置文件
     *
     * @param path
     */
    public synchronized void parse(String path) {
        try {
            if (null == configDigester) {
                initConfigDigester();
            }
            String tempPath =  "classpath:" + uiProperties.getDefaultPath() + path ;
            ClassPathResource pathResource = new ClassPathResource(tempPath);
            if (pathResource.exists()) {
                Resource[] subResources = resourcePatternResolver.getResources(tempPath+pattern);
                if (null != subResources) {
                    for (Resource resource : subResources) {
                        if (resource.exists()) {
                            logger.info("----start load " + resource.getFilename());
                            configDigester.push(this);
                            configDigester.parse(resource.getInputStream());
                        }
                    }
                }
            }
        } catch (IOException ex) {
            logger.error("read page file error", ex);
        } catch (SAXException sa) {
            logger.error("parse page file error", sa);
        }
    }

    public void initConfigDigester() {
        configDigester = new Digester();
        configDigester.setValidating(false);
        configDigester.setUseContextClassLoader(true);
        configDigester.addRuleSet(new ViewRuleSet());
    }

    public void addPage(PageView page) {
        if (pages.containsKey(page.getId())) {
            pages.get(page.getId()).addAllForms(page.getAllForms());
        } else {
            pages.put(page.getId(), page);
        }
    }

    public boolean exists(String pageId, String formId) {
        if (pages.get(pageId) != null) {
            return pages.get(pageId).getForm(formId) != null;
        } else {
            return false;
        }
    }

    public void reload() {
        pages.clear();
        init();
    }

    public PageView findPage(String path) {
        if (!pages.containsKey(path)) {
            parse(path);
        }
        PageView page = pages.get(path);
        if (null == page) {
            logger.error("no find page path:{}" + path);
        }
        return page;
    }



}
